package io.demo.petstore.web;

import static org.assertj.core.api.Java6Assertions.assertThat;

import io.demo.petstore.util.RandomStringBuilder;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
 * <p>
 * Run {@link RegisterBrowserIT} manually. <br/>
 * <strong>DO NOT</strong> run this on maven building era,
 * since it's <strong>TOO EXPENSIVE</strong> to run such thing.
 * </p>
 *
 * @author lijinting01
 */
@Ignore("Too expensive to run such thing during maven build era. Run manually")
public class RegisterBrowserIT {

  private WebDriver driver;

  private RandomStringBuilder randomUsername;

  private RandomStringBuilder randomPassword;

  private RandomStringBuilder randomIdentity;

  private RandomStringBuilder randomPeopleName;

  /**
   * <pre>
   * If you are working behind a proxy server, start the current integration test
   * by providing VM args {@literal -DproxyHost=<host> -DproxyPort=<port>}
   * </pre>
   */
  @Before
  public void setUp() {

    WebDriverManager webDriverManager = WebDriverManager.chromedriver()
        // .forceCache() // use cache if you have downloaded web drivers previously
        // .forceDownload() // download web drivers if you don't have any in repository
        .useMirror();// use http://npm.taobao.org as domestic remote repository, saving much time
    Optional.ofNullable(proxyServer()).ifPresent(webDriverManager::proxy);
    webDriverManager.setup();

    driver = new ChromeDriver();
    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

    randomIdentity = RandomStringBuilder.newBuilder().useDigit();
    randomPassword = RandomStringBuilder.newBuilder().useDigit().useLowerCase().useUpperCase();
    randomPeopleName = RandomStringBuilder.newBuilder().useUpperCase();
    randomUsername = RandomStringBuilder.newBuilder().useLowerCase();
  }

  @Test
  public void registerSuccess() {

    IntStream.range(0, 10).forEach(i -> {
      driver.get("http://localhost:8080/account/register");

      assertThat(driver.getTitle()).isEqualTo("Register Your Account");
      assertThat(isElementPresent(By.id("username"))).isTrue();
      assertThat(isElementPresent(By.id("password"))).isTrue();
      assertThat(isElementPresent(By.id("firstname"))).isTrue();
      assertThat(isElementPresent(By.id("lastname"))).isTrue();
      assertThat(isElementPresent(By.id("identity"))).isTrue();

      final String username = randomUsername.build(6, 20);
      final String password = randomPassword.build(8, 24);
      final String firstName = randomPeopleName.build(5, 16);
      final String lastName = randomPeopleName.build(4, 20);
      final String identity = randomIdentity.build(18);

      driver.findElement(By.id("username")).click();
      driver.findElement(By.id("username")).clear();
      driver.findElement(By.id("username")).sendKeys(username);
      driver.findElement(By.id("password")).clear();
      driver.findElement(By.id("password")).sendKeys(password);
      driver.findElement(By.id("firstname")).clear();
      driver.findElement(By.id("firstname")).sendKeys(firstName);
      driver.findElement(By.id("lastname")).clear();
      driver.findElement(By.id("lastname")).sendKeys(lastName);
      driver.findElement(By.id("identity")).clear();
      driver.findElement(By.id("identity")).sendKeys(identity);
      driver.findElement(By.xpath(
          "(.//*[normalize-space(text()) and normalize-space(.)='Identity*:'])[1]/following::button[1]"))
          .click();

      WebDriverWait webDriverWait = new WebDriverWait(driver, 10);

      webDriverWait.withMessage("Wait too long for the response-")
          .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
          .pollingEvery(Duration.of(1, ChronoUnit.SECONDS))
          .until(ExpectedConditions.visibilityOf(driver.findElement(By.id("info-tips"))));
    });
  }

  private boolean isElementPresent(By by) {
    try {
      driver.findElement(by);
      return true;
    } catch (NoSuchElementException e) {
      return false;
    }
  }


  private String proxyServer() {
    String host = System.getProperty("proxyHost");
    String port = System.getProperty("proxyPort");
    if (Objects.nonNull(System.getProperty("proxyHost"))
        && Objects.nonNull(System.getProperty("proxyPort"))) {
      return host + ":" + port;
    }

    return null;
  }

  @After
  public void tearDown() {
    driver.quit();
  }

}
